package com.oa.realms;

import com.oa.mapper.RoleMapper;
import com.oa.mapper.UserMapper;
import com.oa.pojo.User;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @Author Str
 * @Date 2021/12/17 14:44
 * @Description :AuthorizingRealm是认证+授权的Realm
 * 这里只添加权限就行了
 * 根据用户角色ID，查出该角色的权限Set集合，放进SimpleAuthorizationInfo对象中的setStringPermissions方法中
 */
public class MyAuthorizationRealm extends AuthorizingRealm{

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RoleMapper roleMapper;

    /*---------------------[初始化用户数据]----------------------*/
    public MyAuthorizationRealm() {
        //----[待定]----
    }

    void setPermission(String[] data, Set set) {
        for (String p : data) {
            set.add(p);
        }
    }

    /*---------------------[初始化权限相关数据]-------------------*/
    //{ps}哪些角色有什么权限 ..
    Map<String, Set<String>> rolePermMap = new HashMap();

    public void initRealm() {
        // 这里可以写一些需要初始化的数据，已经在spring-shiro.xml中设定有这个方法
        //{1}暂时写死， 后面再写活。
//        Set<String> r0 = roleMapper.getRolePermission("r0*"); //管理员
//        Set<String> r01 = roleMapper.getRolePermission("r01"); //boss
//        Set<String> r02 = roleMapper.getRolePermission("r02"); //leader
//        Set<String> r03 = roleMapper.getRolePermission("r03"); //manager
//        Set<String> r05 = roleMapper.getRolePermission("r05"); //Employee
//
//        rolePermMap.put("r0*", r0);
//        rolePermMap.put("r01", r01);
//        rolePermMap.put("r02", r02);
//        rolePermMap.put("r03", r03);
//        rolePermMap.put("r05", r05);
//        System.out.println("+---------------------------------------+\n");
//        System.out.println(r02);
//        System.out.println(r05);
//        System.out.println("+---------------------------------------+\n");
    }

    /*---------------------- [END] ----------------------*/
    //Cation: 是做登录认证的。
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
            throws AuthenticationException {
        //{1}得到 用户名。
        String principal = (String) token.getPrincipal();
        //{2}得到用户的密码。
        char[] credentials = (char[]) token.getCredentials();
        String password = new String(credentials);

        //------------------------------[075]-----------------------------
        //{3}从数据库中获取用户信息(数据库中的用户)
        User dbUser = userMapper.login(principal, password);   //<-- 改动这里代码
        if (dbUser == null) {
            return null;  //认证器收到 null 值, 抛出未知用户异常。
        }
        //{4}加密这个信息类稍后再用。
//		new SimpleAuthenticationInfo(principal, hashedCredentials, credentialsSalt, realmName );
        //-------------------------------[088]----------------------------
        //{5}创建认证信息类对象 (不加密的)。[认证器自动判断密码]
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(dbUser, dbUser.getPassword(), this.getName());
        //  {1}数据库用户       {2}数据库的密码        {3}realm名称
        return info;
    }


    //Zation: 是做用户授权 与 权限认证的。
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection collection) {
        //{1}获取主身份信息。(做认证时放入的是 user, 所以这里拿到的是 user)
        User priPrincipal = (User) collection.getPrimaryPrincipal();
        System.out.println("RealmForDouble授权中---->用户："+priPrincipal);
        //+-----------------------------[103]--------------------------------+
        //{2}获取角色 ID (原来是角色名称)
        String roleId = priPrincipal.getRole().getId();      //[12-08 15:19]
        //{3}通过角色名获取角色权限。
        //   {很早已经取到数据, 现在从缓存中获取}
        Set<String> permissions = roleMapper.getRolePermission(roleId);

        //+------------------------------[113]--------------------------------+

        System.out.println("=====================权限集合===================");
        System.out.println(permissions);
        System.out.println("=====================权限集合===================");

        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //{4}添加一个角色
        //info.addRole( roleName );   //<--这里注释掉 [12-08 15:19]
        //{5}还可以设置权限信息。
        info.setStringPermissions(permissions);
        // 将角色权限设置进会话域，可以不用放
        SecurityUtils.getSubject().getSession().setAttribute("permissions", permissions);
        //{6}最后将信息对象返回给授权认证器处理。
        return info;
    }

}